#include "networking.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void createUDPSendingSocket()
{
	if ((iUDPSendingFD = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("Error: Failed to open socket for listening.\n");
		return;
	}
}

void* UDPServerThread(void *vptrPort)
{
	int iPort = *((int *)vptrPort);
	char* sBuffer = malloc(1024 * sizeof(char));
	int iSocketFD, iSizeOfRemoteAddress, iBytesRecieved;
	struct sockaddr_in objSocketAddress, objRemoteAddress;

	iSizeOfRemoteAddress = sizeof(struct sockaddr);

	
	if ((iSocketFD = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
	{
		printf("Error: Failed to open socket for listening.\n");
		return NULL;
	}

	memset(&objSocketAddress, 0x00, sizeof(struct sockaddr_in));
	objSocketAddress.sin_family = PF_INET;
	objSocketAddress.sin_addr.s_addr = htonl(INADDR_ANY);
	objSocketAddress.sin_port = htons(iPort);
	
	if (bind(iSocketFD, (struct sockaddr *)&objSocketAddress, sizeof(struct sockaddr_in)) != 0)
	{
		printf("Error: Failed to bind socket for listening.\n");
		return NULL;
	}

	while ((iBytesRecieved = recvfrom(iSocketFD, sBuffer, 1024, 0, (struct sockaddr *)&objRemoteAddress, &iSizeOfRemoteAddress)) > 0)
		processMessage(sBuffer, iBytesRecieved, objRemoteAddress);

	return NULL;
}

void broadcastMessage(void *vptrBuffer, int iBufferLength)
{
	void *vptrNewBuffer = malloc(iBufferLength + sizeof(int));
	memcpy(vptrNewBuffer, &iSelfServerPort, sizeof(int));
	memcpy(vptrNewBuffer + sizeof(int), vptrBuffer, iBufferLength);
	doBroadcastMessage(vptrNewBuffer, iBufferLength + sizeof(int));
	free(vptrNewBuffer);
}


void doBroadcastMessage(void *vptrBuffer, int iBufferLength)
{
	/*
	   [TASK #1]

	   Send a UDP packet containing the contents of vptrBuffer (which is of length
	   iBufferLength) to all ports except your own port (stored in the global
	   variable iSelfServerPort) in the inclusive range of [iFirstPortNumber,
	   iFirstPortNumber + iMaxPlayers].

	   For example, if vptrBuffer points to a series of chars { 0x01, 0x13, 0x14 }
	   and the value of iBufferLength is 3, you would need to send a UDP packet
	   containing those three chars to every port in the range.

	   You can assume that you have a network descriptor iUDPSendingFD that has
	   already been set up for you to use to send UDP packets.
	*/

   struct sockaddr_in dest;
   dest.sin_family = AF_INET;
   dest.sin_addr.s_addr = inet_addr ( "127.0.0.1" );
   memset ( dest.sin_zero, '\0', sizeof ( dest.sin_zero ));
   int size = sizeof ( dest );
   unsigned short i;
   for ( i = iFirstPortNumber; i < ( iFirstPortNumber + iMaxPlayers + 1); i++ )
   {
      if ( i != iSelfServerPort )
      {
         dest.sin_port = htons ( i );
         size_t send_size = sendto ( iUDPSendingFD, vptrBuffer, iBufferLength, 0, ( struct sockaddr *) &dest, sizeof ( dest ));
      }
   }

	/*
	   Finish [TASK #1] between the [TASK #1] description and this comment.
	*/
}
